#ifndef _SERVERBASE_H_
#define _SERVERBASE_H_

#define BOOST_ALL_NO_LIB
#define MAX_THREAD					16
#define BUFFER_TCP_PACK				1472

#include <boost/asio.hpp>
#include <boost/smart_ptr/enable_shared_from_this.hpp>
#include <boost/function.hpp>
#include "../memorypool/memorypool.h"

#ifdef _WIN32
#include "../pthread/pthread.h"
#else
#include <pthread.h>
#endif

class CTcpPeer;
// typedef boost::function< CTcpPeer*(boost::asio::io_service&) >	NEWPEER;
typedef CTcpPeer*	(*NEWPEER)(boost::asio::io_service&);

class CTcpListen;
class CTcpAcceptor : public boost::enable_shared_from_this<CTcpAcceptor>
{
	friend class CTcpListen;
private:
	CTcpAcceptor(boost::asio::io_service& ios, 
		boost::asio::ip::tcp::endpoint& ep, 
		boost::system::error_code& ec,
		NEWPEER peer);

	void	NextAccept();
	void	AcceptHandle(boost::system::error_code ec, CTcpPeer* peer);
private:
	boost::asio::ip::tcp::acceptor	m_acceptor;
	NEWPEER							m_newpeer;

};

class CTcpListen
{
public:
	CTcpListen();
	virtual ~CTcpListen();

public:
	bool		InitListen(unsigned int nThreads);	
	bool		Listen(unsigned short, NEWPEER fun);
	void		Run();
	boost::asio::io_service& GetIoService();

public:
	void			Stop();
	static void*	ThreadProc(void* param);

private:
	boost::asio::io_service			m_ios;
	bool							m_bStop;
	unsigned int					m_nThreads;
	pthread_t						m_idThreads[MAX_THREAD];

};

class CTcpPeer : public mpool::object
{
	friend class CTcpAcceptor;
public:
	CTcpPeer(boost::asio::io_service& ios);
	virtual ~CTcpPeer();

public:
	boost::asio::ip::tcp::socket&		GetSocket();
	boost::asio::io_service&			GetIoService();
	int									Send(const unsigned char* pData, int nLen);
	void								Lock();
	void								Unlock();

	static CTcpPeer*					CreateTcpPeer(boost::asio::io_service& ios);

public:
	virtual void	OnConnect();
	virtual	size_t	OnRecv(unsigned char* pData, size_t nLen);

private:
	void			NextRecv(size_t offset = 0);
	void			NextSend();
	void			RecvHandle(boost::system::error_code ec, size_t bytes_transferred, size_t offset);
	void			SendHandle(boost::system::error_code ec, size_t bytes_transferred, size_t all);

private:
	boost::asio::ip::tcp::socket		m_sock;
	bool								m_bReadySend;
	bool								m_blocked;
	std::vector< unsigned char, mpool::allocator<unsigned char> >
										m_vctSendBuff;
	unsigned char						m_szRecvBuff[BUFFER_TCP_PACK];
	unsigned char						m_szSendBuff[BUFFER_TCP_PACK];
};

#endif // _SERVERBASE_H_
